home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacPerl 5.0.3 / MacPerl Source ƒ / Perl5 / ext / MacPerl / MacPerl.xs < prev    next >
Encoding:
Text File  |  1995-11-18  |  14.5 KB  |  640 lines  |  [TEXT/MPS ]

  1. /* $Header: tyrathect:Development:Perl::RCS:missing.c,v 1.2 1994/05/04 02:12:43 neeri Exp $
  2.  *
  3.  *    Copyright (c) 1995 Matthias Neeracher
  4.  *
  5.  *    You may distribute under the terms of the Perl Artistic License,
  6.  *    as specified in the README file.
  7.  *
  8.  * $Log: missing.c,v $
  9.  */
  10.  
  11. #define MAC_CONTEXT
  12.  
  13. #include "EXTERN.h"
  14. #include "perl.h"
  15. #include "XSUB.h"
  16. #include <Types.h>
  17. #include <QuickDraw.h>
  18. #include <Dialogs.h>
  19. #include <Lists.h>
  20. #include <TFileSpec.h>
  21. #include <Files.h>
  22. #include <Fonts.h>
  23. #include <Resources.h>
  24.  
  25. /* Shamelessly borrowed from Apple's includes. Sorry */
  26.  
  27. /*
  28.  * faccess() commands; for general use
  29.  */
  30.                      /* 'd' => "directory" ops */
  31. #define F_DELETE        (('d'<<8)|0x01)
  32. #define F_RENAME        (('d'<<8)|0x02)
  33.  
  34. /*
  35.  * more faccess() commands; for use only by MPW tools
  36.  */
  37.  
  38. #define F_OPEN             (('d'<<8)|0x00)        /* reserved for operating system use */
  39.                     /* 'e' => "editor" ops */
  40. #define F_GTABINFO         (('e'<<8)|0x00)        /* get tab offset for file */    
  41. #define F_STABINFO         (('e'<<8)|0x01)        /* set     "    "        "    "  */
  42. #define F_GFONTINFO        (('e'<<8)|0x02)        /* get font number and size for file */
  43. #define F_SFONTINFO        (('e'<<8)|0x03)        /* set     "        "    "    "    "    "      */
  44. #define F_GPRINTREC        (('e'<<8)|0x04)        /* get print record for file */
  45. #define F_SPRINTREC        (('e'<<8)|0x05)        /* set     "        "    "    "      */
  46. #define F_GSELINFO         (('e'<<8)|0x06)        /* get selection information for file */
  47. #define F_SSELINFO         (('e'<<8)|0x07)        /* set        "        "        "        " */
  48. #define F_GWININFO         (('e'<<8)|0x08)        /* get current window position */
  49. #define F_SWININFO         (('e'<<8)|0x09)        /* set    "        "        "        */
  50. #define F_GSCROLLINFO    (('e'<<8)|0x0A)        /* get scroll information */
  51. #define F_SSCROLLINFO    (('e'<<8)|0x0B)        /* set    "           "        */
  52. #define F_GMARKER        (('e'<<8)|0x0D)        /* Get Marker */
  53. #define F_SMARKER        (('e'<<8)|0x0C)        /* Set   "       */
  54. #define F_GSAVEONCLOSE    (('e'<<8)|0x0F)        /* Get Save on close */
  55. #define F_SSAVEONCLOSE    (('e'<<8)|0x0E)        /* Set   "     "     "      */
  56.  
  57. /*
  58.  *    argument structure for use with F_SMARKER command
  59.  */
  60. #ifdef powerc
  61. #pragma options align=mac68k
  62. #endif
  63. struct MarkElement {
  64.     int                start;            /* start position of mark */
  65.     int                end;            /* end position */
  66.     unsigned char    charCount;        /* number of chars in mark name */
  67.     char            name[64];        /* marker name */
  68. };                                    /* note: marker may be up to 64 chars long */
  69.  
  70. #ifdef powerc
  71. #pragma options align=reset
  72. #endif
  73.  
  74. #ifndef __cplusplus
  75. typedef struct MarkElement MarkElement;
  76. #endif
  77.  
  78. #ifdef powerc
  79. #pragma options align=mac68k
  80. #endif
  81. struct SelectionRecord {
  82.     long    startingPos;
  83.     long    endingPos;
  84.     long    displayTop;
  85. };
  86. #ifdef powerc
  87. #pragma options align=reset
  88. #endif
  89. #ifndef __cplusplus
  90. typedef struct SelectionRecord SelectionRecord;
  91. #endif
  92.  
  93. static char gMacPerlScratch[256];
  94. #define gMacPerlScratchString ((StringPtr) gMacPerlScratch)
  95.  
  96. static ControlHandle GetDlgCtrl(DialogPtr dlg, short item)
  97. {
  98.     short     kind;
  99.     Handle    hdl;
  100.     Rect    box;
  101.     
  102.     GetDItem(dlg, item, &kind, &hdl, &box);
  103.     return (ControlHandle) hdl;
  104. }
  105.  
  106. static void GetDlgText(DialogPtr dlg, short item, StringPtr text)
  107. {
  108.     GetIText((Handle) GetDlgCtrl(dlg, item), text);
  109. }
  110.  
  111. static void SetDlgText(DialogPtr dlg, short item, char * text)
  112. {
  113.     setitext((Handle) GetDlgCtrl(dlg, item), text);
  114. }
  115.  
  116. static void GetDlgRect(DialogPtr dlg, short item, Rect * r)
  117. {
  118.     short     kind;
  119.     Handle    hdl;
  120.     
  121.     GetDItem(dlg, item, &kind, &hdl, r);
  122. }
  123.  
  124. static void FrameDlgRect(DialogPtr dlg, short item)
  125. {
  126.     Rect    r;
  127.     
  128.     GetDlgRect(dlg, item, &r);
  129.     InsetRect(&r, -4, -4);
  130.     PenSize(3, 3);
  131.     FrameRoundRect(&r, 16, 16);
  132.     PenSize(1,1);
  133. }
  134.  
  135. static ListHandle gPickList = NULL;
  136.  
  137. #define SetCell(cell, row, column)    { (cell).h = column; (cell).v = row; }
  138. #define ROW(cell)                     (cell).v
  139.  
  140. pascal void
  141. MacListUpdate(myDialog, myItem)
  142. DialogPtr        myDialog;
  143. short            myItem;
  144. {
  145.     Rect            myrect;
  146.  
  147.     LUpdate(myDialog->visRgn, gPickList);
  148.     myrect = (**(gPickList)).rView;
  149.     InsetRect(&myrect, -1, -1);
  150.     FrameRect(&myrect);
  151. }
  152.  
  153. #if USESROUTINEDESCRIPTORS
  154. RoutineDescriptor    uMacListUpdate = 
  155.         BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, MacListUpdate);
  156. #else
  157. #define uMacListUpdate MacListUpdate
  158. #endif
  159.  
  160. pascal Boolean
  161. MacListFilter(myDialog, myEvent, myItem)
  162. DialogPtr        myDialog;
  163. EventRecord        *myEvent;
  164. short            *myItem;
  165. {
  166.     Rect    listrect;
  167.     short    myascii;
  168.     Handle    myhandle;
  169.     Point    mypoint;
  170.     short    mytype;
  171.     int        activate;
  172.  
  173.     SetPort(myDialog);
  174.     if (myEvent->what == keyDown) {
  175.         myascii = myEvent->message % 256;
  176.         if (myascii == '\015' || myascii == '\003') {    /* This is return or enter... */
  177.             *myItem = 1;
  178.             return true;
  179.             }
  180.         }
  181.     else if (myEvent->what == mouseDown) {
  182.         mypoint = myEvent->where;
  183.         GlobalToLocal(&mypoint);
  184.         GetDItem(myDialog, 4, &mytype, &myhandle, &listrect);
  185.         if (PtInRect(mypoint, &listrect) && gPickList != NULL) {
  186.             if (LClick(mypoint, (short)myEvent->modifiers, gPickList)) {
  187.                 /* User double-clicked in cell... */
  188.                 *myItem = 1;
  189.                 return true;
  190.                 }
  191.             }
  192.         }
  193.     else if (myEvent->what == activateEvt && gPickList != NULL) {
  194.         activate = (myEvent->modifiers & 0x01) != 0;
  195.         LActivate((Boolean) activate, gPickList);
  196.         }
  197.     
  198.     return false;
  199. }
  200.  
  201. #if USESROUTINEDESCRIPTORS
  202. RoutineDescriptor    uMacListFilter = 
  203.         BUILD_ROUTINE_DESCRIPTOR(uppModalFilterProcInfo, MacListFilter);
  204. #else
  205. #define uMacListFilter MacListFilter
  206. #endif
  207.  
  208. static OSErr GetVolInfo(short volume, Boolean indexed, FSSpec * spec)
  209. {
  210.     OSErr                err;
  211.     HParamBlockRec    pb;
  212.     
  213.     pb.volumeParam.ioNamePtr    =    spec->name;
  214.     pb.volumeParam.ioVRefNum    =    indexed ? 0 : volume;
  215.     pb.volumeParam.ioVolIndex    =    indexed ? volume : 0;
  216.     
  217.     if (err = PBHGetVInfoSync(&pb))
  218.         return err;
  219.     
  220.     spec->vRefNum    =    pb.volumeParam.ioVRefNum;
  221.     spec->parID        =    1;
  222.     
  223.     return noErr;
  224. }
  225.  
  226. MODULE = MacPerl    PACKAGE = MacPerl    PREFIX = MP_
  227.  
  228. void
  229. MP_SetFileInfo(creator, type, path, ...)
  230.     OSType    creator
  231.     OSType    type
  232.     char *    path
  233.     CODE:
  234.     {
  235.         int i;
  236.         for (i=2; i<items; i++)
  237.             fsetfileinfo((char *) SvPV(ST(i), na), creator, type);
  238.     }
  239.  
  240. void
  241. MP_GetFileInfo(path)
  242.     char *    path
  243.     PPCODE:
  244.     {
  245.         unsigned long    creator;
  246.         unsigned long    type;
  247.         fgetfileinfo(path, &creator, &type);
  248.             
  249.         if (errno) {
  250.             if (GIMME != G_ARRAY)
  251.                 XPUSHs(&sv_undef);
  252.             /* Else return empty list */
  253.         } else if (GIMME != G_ARRAY) {
  254.             XPUSHs(sv_2mortal(newSVpv((char *) &type, 4)));
  255.         } else {
  256.             XPUSHs(sv_2mortal(newSVpv((char *) &creator, 4)));
  257.             XPUSHs(sv_2mortal(newSVpv((char *) &type, 4)));
  258.         }
  259.     }
  260.  
  261. char *
  262. MP_Ask(prompt, ...)
  263.     char *    prompt
  264.     CODE:
  265.     {
  266.         short            item;
  267.         DialogPtr    dlg;
  268.         
  269.         dlg = GetNewDialog(2010, NULL, (WindowPtr)-1);
  270.         InitCursor();
  271.         SetDlgText(dlg, 3, prompt);
  272.         
  273.         if (items > 1)
  274.             SetDlgText(dlg, 4, (char *) SvPV(ST(1), na));
  275.         SelIText(dlg, 4, 0, 1024);
  276.         
  277.         ShowWindow(dlg);
  278.         SetPort(dlg);
  279.         FrameDlgRect(dlg, ok);
  280.         ModalDialog((ModalFilterUPP)0, &item);
  281.         switch (item) {
  282.         case ok:
  283.             GetDlgText(dlg, 4, gMacPerlScratchString);
  284.             ST(0) = sv_2mortal(newSVpv(gMacPerlScratch+1, gMacPerlScratch[0]));
  285.             break;
  286.         case cancel:
  287.             ST(0) = &sv_undef;
  288.             break;
  289.         }
  290.         DisposeDialog(dlg);
  291.     }
  292.  
  293. int
  294. MP_Answer(prompt, ...)
  295.     char *    prompt
  296.     CODE:
  297.     {
  298.         short            item;
  299.         DialogPtr    dlg;
  300.         
  301.         if (items > 4)
  302.             items = 4;
  303.             
  304.         dlg = GetNewDialog((items>1) ? 1999+items : 2001, NULL, (WindowPtr)-1);
  305.         InitCursor();
  306.         SetDlgText(dlg, 5, prompt);
  307.         
  308.         if (items > 1)
  309.             for (item = 1; item < items; item++) {
  310.                 strcpy(gMacPerlScratch+1, (char *) SvPV(ST(item), na));
  311.                 *gMacPerlScratchString = strlen(gMacPerlScratch+1);
  312.                 SetCTitle(GetDlgCtrl(dlg, item), gMacPerlScratchString);
  313.             }
  314.         else
  315.             SetCTitle(GetDlgCtrl(dlg, 1), "\pOK");
  316.             
  317.         ShowWindow(dlg);
  318.         SetPort(dlg);
  319.         FrameDlgRect(dlg, ok);
  320.         ModalDialog((ModalFilterUPP)0, &item);
  321.         DisposeDialog(dlg);
  322.         
  323.         RETVAL = (items > 1) ? items - item - 1 : 0;
  324.     }
  325.     OUTPUT:
  326.     RETVAL
  327.  
  328. void
  329. MP_Choose(domain, type, prompt, ...)
  330.     int        domain
  331.     int        type
  332.     char *    prompt
  333.     CODE:
  334.     {
  335.         int          flags;
  336.         STRLEN    len;
  337.         char *     constraint;
  338.         char *     def_addr;
  339.         
  340.         constraint = (items>=4) ? ((char *) SvPV(ST(3), len)) : nil;
  341.         constraint = constraint && len ? constraint : nil;
  342.         flags = (items>=5) ? ((int) SvIV(ST(4))) : 0;
  343.         def_addr = (items>=6) ? ((char *) SvPV(ST(5), len)) : nil;
  344.         def_addr = def_addr && len ? def_addr : nil;
  345.         
  346.         gMacPerlScratch[0] = 0;
  347.         
  348.         if (def_addr) {
  349.             memcpy(gMacPerlScratch, def_addr, len);
  350.             gMacPerlScratch[len] = 0;    /* Some types require this */
  351.         } 
  352.         len = 256;                            /* Len is output only! */
  353.         
  354.         if (choose(domain, type, prompt, constraint, flags, gMacPerlScratch, &len) < 0)
  355.             ST(0) = &sv_undef;
  356.         else
  357.             ST(0) = sv_2mortal(newSVpv(gMacPerlScratch, len));
  358.     }
  359.  
  360. void
  361. MP_Pick(prompt, ...)
  362.     char *    prompt
  363.     CODE:
  364.     {    
  365.         short            itemHit;
  366.         STRLEN        len;
  367.         Boolean        done;
  368.         DialogPtr    dlg;
  369.         ListHandle    mylist;
  370.         Cell            mycell;
  371.         short            mytype;
  372.         Handle        myhandle;
  373.         Point            cellsize;
  374.         Rect            listrect, dbounds;
  375.         char    *        item;
  376.             
  377.         InitCursor();
  378.         dlg = GetNewDialog(2020, NULL, (WindowPtr)-1);
  379.         
  380.         SetDlgText(dlg, 3, prompt);
  381.         GetDItem(dlg, 4, &mytype, &myhandle, &listrect);
  382.         SetDItem(dlg, 4, mytype, (Handle)&uMacListUpdate, &listrect);
  383.         
  384.         SetPort(dlg);
  385.         InsetRect(&listrect, 1, 1);
  386.         SetRect(&dbounds, 0, 0, 1, items-1);
  387.         cellsize.h = (listrect.right - listrect.left);
  388.         cellsize.v = 17;
  389.     
  390.         listrect.right -= 15;
  391.     
  392.         gPickList = LNew(&listrect, &dbounds, cellsize, 0,
  393.                                 dlg, true, false, false, true);
  394.     
  395.         LDoDraw(false, gPickList);
  396.         
  397.         SetCell(mycell, 0, 0);
  398.         for (; mycell.v<items-1; ++mycell.v)    {
  399.             item = (char *) SvPV(ST(mycell.v+1), len);
  400.             LSetCell(item, len, mycell, gPickList);
  401.         }
  402.     
  403.         LDoDraw(true, gPickList);
  404.         ShowWindow(dlg);
  405.         
  406.         for (done=false; !done; ) {
  407.             SetPort(dlg);
  408.             FrameDlgRect(dlg, ok);
  409.             ModalDialog((ModalFilterUPP) &uMacListFilter, &itemHit);
  410.             switch (itemHit) {
  411.             case ok:
  412.                 SetCell(mycell, 0, 0);
  413.                 done = true;
  414.                 if (!LGetSelect(true, &mycell, gPickList))
  415.                     itemHit = cancel;
  416.                 break;
  417.             case cancel:
  418.                 done = true;
  419.                 break;
  420.             }
  421.         }    /* Modal Loop */
  422.     
  423.         SetPort(dlg);
  424.         
  425.         LDispose(gPickList);
  426.         gPickList = nil;
  427.         DisposDialog(dlg);
  428.         
  429.         if (itemHit == ok)
  430.             ST(0) = sv_mortalcopy(ST(mycell.v+1));
  431.         else
  432.             ST(0) = &sv_undef;
  433.     }
  434.  
  435. void
  436. MP_Quit(condition)
  437.     int    condition
  438.     CODE:
  439.     gPerlQuit = condition;
  440.  
  441. void
  442. MP_FAccess(file, cmd, ...)
  443.     char *    file
  444.     unsigned    cmd
  445.     PPCODE:
  446.     {
  447.         unsigned                uarg;
  448.         Rect                    rarg;
  449.         SelectionRecord    sarg;
  450.         char *                 name;
  451.         
  452.         switch (cmd) {
  453.         case F_GFONTINFO:
  454.             if (faccess(file, cmd, (long *)&uarg) < 0)
  455.                 XPUSHs(&sv_undef);
  456.             else if (GIMME != G_ARRAY)
  457.                 XPUSHs(sv_2mortal(newSViv(uarg >> 16)));
  458.             else {
  459.                 GetFontName(uarg >> 16, gMacPerlScratchString);
  460.                 XPUSHs(sv_2mortal(newSVpv(gMacPerlScratch+1, *gMacPerlScratch)));
  461.                 XPUSHs(sv_2mortal(newSViv(uarg & 0xFFFF)));
  462.             }
  463.             break;
  464.         case F_GSELINFO:
  465.             if (faccess(file, cmd, (long *)&sarg) < 0)
  466.                 XPUSHs(&sv_undef);
  467.             else if (GIMME != G_ARRAY)
  468.                 XPUSHs(sv_2mortal(newSViv(sarg.startingPos)));
  469.             else {
  470.                 XPUSHs(sv_2mortal(newSViv(sarg.startingPos)));
  471.                 XPUSHs(sv_2mortal(newSViv(sarg.endingPos)));
  472.                 XPUSHs(sv_2mortal(newSViv(sarg.displayTop)));
  473.             }
  474.             break;
  475.         case F_GTABINFO:
  476.             if (faccess(file, cmd, (long *)&uarg) < 0) 
  477.                 XPUSHs(&sv_undef);
  478.             else
  479.                 XPUSHs(sv_2mortal(newSViv(uarg)));
  480.             break;
  481.         case F_GWININFO:
  482.             if (faccess(file, cmd, (long *)&rarg) < 0)
  483.                 XPUSHs(&sv_undef);
  484.             else if (GIMME != G_ARRAY)
  485.                 XPUSHs(sv_2mortal(newSViv(rarg.top)));
  486.             else {
  487.                 XPUSHs(sv_2mortal(newSViv(rarg.left)));
  488.                 XPUSHs(sv_2mortal(newSViv(rarg.top)));
  489.                 XPUSHs(sv_2mortal(newSViv(rarg.right)));
  490.                 XPUSHs(sv_2mortal(newSViv(rarg.bottom)));
  491.             }
  492.             break;
  493.         case F_SFONTINFO:
  494.             if (items < 3)
  495.                 croak("Usage: MacPerl::FAccess(file, F_SFONTINFO, font [, size])");
  496.             
  497.             name = SvPV(ST(2), na);
  498.             
  499.             if (items == 3) {
  500.                 if (faccess(file, F_GFONTINFO, (long *)&uarg) < 0)
  501.                     uarg = 9;
  502.             } else
  503.                 uarg = (unsigned) SvIV(ST(3));
  504.             
  505.             if (isalpha(*name)) {
  506.                 short    family;
  507.                 
  508.                 getfnum(name, &family);
  509.                 
  510.                 uarg = (uarg & 0xFFFF) | ((unsigned) family) << 16;
  511.             } else 
  512.                 uarg = (uarg & 0xFFFF) | ((unsigned) SvIV(ST(2))) << 16;
  513.             
  514.             if (faccess(file, cmd, (long *)uarg) < 0)
  515.                 XPUSHs(&sv_undef);
  516.             else
  517.                 XPUSHs(sv_2mortal(newSViv(1)));
  518.             break;
  519.         case F_SSELINFO:
  520.             if (items < 4)
  521.                 croak("Usage: MacPerl::FAccess(file, F_SSELINFO, start, end [, top])");
  522.             
  523.             if (items == 4) {
  524.                 if (faccess(file, F_GSELINFO, (long *) &sarg) < 0) 
  525.                     sarg.displayTop = SvIV(ST(2));
  526.             } else 
  527.                 sarg.displayTop = SvIV(ST(4));
  528.                 
  529.             sarg.startingPos = SvIV(ST(2));
  530.             sarg.endingPos = SvIV(ST(3));
  531.             
  532.             if (faccess(file, cmd, (long *)&sarg) < 0)
  533.                 XPUSHs(&sv_undef);
  534.             else
  535.                 XPUSHs(sv_2mortal(newSViv(1)));
  536.             break;
  537.         case F_STABINFO:
  538.             if (items < 3)
  539.                 croak("Usage: MacPerl::FAccess(file, F_STABINFO, tab)");
  540.             
  541.             uarg = SvIV(ST(2));
  542.             
  543.             if (faccess(file, cmd, (long *)uarg) < 0) 
  544.                 XPUSHs(&sv_undef);
  545.             else
  546.                 XPUSHs(sv_2mortal(newSViv(1)));
  547.             break;
  548.         case F_SWININFO:
  549.             if (items < 4 )
  550.                 croak("Usage: MacPerl::FAccess(file, F_SWININFO, left, top [, right [, bottom]])");
  551.             
  552.             if (items < 6) {
  553.                 if (faccess(file, F_GWININFO, (long *)&rarg) < 0)
  554.                     rarg.bottom = rarg.right = 400;
  555.                 else {
  556.                     rarg.bottom = rarg.bottom - rarg.top + (short) SvIV(ST(3));
  557.                     if (items == 4)
  558.                         rarg.right = rarg.right - rarg.left + (short) SvIV(ST(2));
  559.                 }
  560.             } else {
  561.                 rarg.right = (short) SvIV(ST(4));
  562.                 rarg.bottom = (short) SvIV(ST(5));
  563.             }
  564.                 
  565.             rarg.left = (short) SvIV(ST(2));
  566.             rarg.top = (short) SvIV(ST(3));
  567.             
  568.             if (faccess(file, cmd, (long *)&rarg) < 0)
  569.                 XPUSHs(&sv_undef);
  570.             else
  571.                 XPUSHs(sv_2mortal(newSViv(1)));
  572.             break;
  573.         default:
  574.             croak("MacPerl::FAccess() can't handle this command");
  575.         }
  576.     }
  577.  
  578. void
  579. MP_MakeFSSpec(path)
  580.     char *    path
  581.     CODE:
  582.     {
  583.         FSSpec    spec;
  584.         
  585.         if (Path2FSSpec(path, &spec))
  586.              ST(0) = &sv_undef;
  587.         else
  588.             ST(0) = sv_2mortal(newSVpv(FSp2Encoding(&spec), 0));
  589.     }
  590.  
  591. void
  592. MP_MakePath(path)
  593.     char *    path
  594.     CODE:    
  595.     {
  596.         FSSpec    spec;
  597.         
  598.         if (Path2FSSpec(path, &spec))
  599.              ST(0) = &sv_undef;
  600.         else
  601.             ST(0) = sv_2mortal(newSVpv(FSp2FullPath(&spec), 0));
  602.     }
  603.  
  604. void
  605. MP_Volumes()
  606.     PPCODE:
  607.     {
  608.         FSSpec spec;
  609.         
  610.         if (GIMME != G_ARRAY) {
  611.             Special2FSSpec('macs', kOnSystemDisk, 0, &spec);
  612.             GetVolInfo(spec.vRefNum, false, &spec);
  613.             
  614.             XPUSHs(sv_2mortal(newSVpv(FSp2Encoding(&spec), 0)));
  615.         } else {
  616.             short    index;
  617.             
  618.             for (index = 0; !GetVolInfo(index+1, true, &spec); ++index)
  619.                 XPUSHs(sv_2mortal(newSVpv(FSp2Encoding(&spec), 0)));
  620.         }
  621.     }
  622.  
  623. BOOT:
  624.     {
  625.         extern int    StandAlone;
  626.         VersRecHndl    vers         = (VersRecHndl) GetResource('vers', 1);
  627.         int             versLen    = *(*vers)->shortVersion;
  628.         SV *            version    = perl_get_sv("MacPerl::Version", TRUE);
  629.  
  630.         HLock((Handle) vers);
  631.         memcpy(gMacPerlScratch, (char *)(*vers)->shortVersion+1, versLen);
  632.         if (StandAlone) 
  633.             strcpy(gMacPerlScratch+versLen, " Application");
  634.         else
  635.             strcpy(gMacPerlScratch+versLen, " MPW");
  636.         
  637.         sv_setpv(version, gMacPerlScratch);
  638.         SvREADONLY_on(version);
  639.     }
  640.